package service

import (
	"ams/dao"
	"fmt"
	"github.com/jinzhu/copier"
	"gorm.io/gorm"
	"lib/id"
	"lib/structs/ams"
	"lib/structs/tables"
	"time"
)

var AssetService = new(assetService)

type assetService struct {
}

func (s assetService) AddAssetConsLogs(in tables.AmsAssetConsLog) (err error) {
	var asm tables.AmsAsset
	asm, err = dao.AssetDao.FindById(in.AssetId)
	if err != nil {
		return err
	}
	switch in.OperationType {
	case "in":
		asm.Num = asm.Num + in.Num
	case "out":
		if asm.Num < in.Num {
			err = fmt.Errorf("耗材库存不足！当前库存：%d,出库数量：%d", asm.Num, in.Num)
			return err
		} else {
			asm.Num = asm.Num - in.Num
		}
	default:
		err = fmt.Errorf("未定义的操作类型")
		return err
	}
	err = dao.DB.Transaction(func(tx *gorm.DB) error {
		err = tx.Save(&asm).Error
		if err != nil {
			return err
		}
		in.Id = id.GetSnowId()
		in.CreateAt = time.Now().Unix()
		err = tx.Create(&in).Error
		return err
	})
	return err
}

func (s assetService) AssetConsPage(in ams.SearchAssetDto) (li []ams.AssetDto, total int64, err error) {
	var assets []tables.AmsAsset
	assets, total, err = dao.AssetDao.PageForCons(in)
	if err != nil {
		err = fmt.Errorf(err.Error())
		return
	}
	typeMap := s.getAssetTypeMap()
	categoryMap := s.getAssetCategoryMap()
	for _, item := range assets {
		li = append(li, ams.AssetDto{
			Id:           item.Id,
			AssetCode:    item.AssetCode,
			LabelType:    item.LabelType,
			LabelCode:    item.LabelCode,
			Name:         item.Name,
			TypeId:       item.TypeId,
			TypeName:     typeMap[item.TypeId].Name,
			CategoryId:   item.CategoryId,
			CategoryName: categoryMap[item.CategoryId].Name,
			Tag:          item.Tag,
			Description:  item.Description,
			Price:        item.Extend.Price,
			BuyAt:        item.Extend.BuyAt,
			ExpirationAt: item.Extend.ExpirationAt,
			Num:          item.Num,
		})
	}
	return
}

func (s assetService) AssetConsLogsPage(in ams.SearchAssetConsDto) (li []ams.AssetConsLogsDto, total int64, err error) {
	li = make([]ams.AssetConsLogsDto, 0)
	var (
		logs   []tables.AmsAssetConsLog
		asList []ams.AssetConsListDto
	)
	logs, total, err = dao.AssetDao.PageForConsLog(in)
	if err != nil {
		return
	}
	asList, err = dao.AssetDao.AssetConsList()
	if err != nil {
		return
	}
	asMap := make(map[int64]ams.AssetConsListDto)
	for _, item := range asList {
		asMap[item.AssetId] = item
	}
	for _, item := range logs {
		li = append(li, ams.AssetConsLogsDto{
			Id:            item.Id,
			AssetId:       item.AssetId,
			OperationType: item.OperationType,
			Num:           item.Num,
			Unit:          item.Unit,
			Applicant:     item.Applicant,
			Operator:      item.Operator,
			Admin:         item.Admin,
			CreateAt:      item.CreateAt,
			OrderCode:     item.OrderCode,
			Notes:         item.Notes,
			Picture:       item.Picture,
			AssetName:     asMap[item.AssetId].Name,
			AssetDesc:     asMap[item.AssetId].Description,
		})
	}
	return li, total, nil
}
func (s assetService) Page(in ams.SearchAssetDto) (li []ams.AssetDto, total int64, err error) {
	var assets []tables.AmsAsset
	assets, total, err = dao.AssetDao.Page(in)
	if err != nil {
		err = fmt.Errorf(err.Error())
		return
	}
	typeMap := s.getAssetTypeMap()
	categoryMap := s.getAssetCategoryMap()
	for _, item := range assets {
		li = append(li, ams.AssetDto{
			Id:           item.Id,
			AssetCode:    item.AssetCode,
			LabelType:    item.LabelType,
			LabelCode:    item.LabelCode,
			Name:         item.Name,
			TypeId:       item.TypeId,
			TypeName:     typeMap[item.TypeId].Name,
			CategoryId:   item.CategoryId,
			CategoryName: categoryMap[item.CategoryId].Name,
			Tag:          item.Tag,
			Description:  item.Description,
			Price:        item.Extend.Price,
			BuyAt:        item.Extend.BuyAt,
			ExpirationAt: item.Extend.ExpirationAt,
		})
	}
	return
}
func (s assetService) Add(in ams.AddAssetDto) (err error) {
	var (
		am  tables.AmsAsset
		exm tables.AmsAssetExtend
	)
	err = copier.Copy(&am, in)
	if err != nil {
		err = fmt.Errorf("copier.Copy failed, err:%v", err)
	}
	err = copier.Copy(&exm, in)
	if err != nil {
		err = fmt.Errorf("copier.Copy failed, err:%v", err)
	}
	err = dao.AssetDao.Create(am, exm)
	return err
}

func (s assetService) DeleteById(id int64) (err error) {
	err = dao.AssetDao.DeleteById(id)
	return err
}

// AssetCategoryNode 递归组织树形结构
func (s assetService) AssetCategoryNode(parentId int64, li []ams.AssetCategoryNode) (tree []ams.AssetCategoryNode) {
	for _, v := range li {
		if v.ParentId == parentId {
			node := ams.AssetCategoryNode{
				Value:       v.Value,
				Label:       v.Label,
				Description: v.Description,
				ParentId:    v.ParentId,
				Children:    []ams.AssetCategoryNode{},
			}
			subs := s.AssetCategoryNode(v.Value, li)
			node.Children = append(node.Children, subs...)
			tree = append(tree, node)
		}
	}
	return tree
}

func (s assetService) getAssetTypeMap() (m map[int64]tables.AmsAssetType) {
	m = make(map[int64]tables.AmsAssetType)
	li, err := dao.AssetDao.FindTypeList()
	if err != nil {
		return
	}
	for _, item := range li {
		m[item.Id] = item
	}
	return
}
func (s assetService) getAssetCategoryMap() (m map[int64]tables.AmsAssetCategory) {
	m = make(map[int64]tables.AmsAssetCategory)
	li, err := dao.AssetDao.FindCategoryList()
	if err != nil {
		return
	}
	for _, item := range li {
		m[item.Id] = item
	}
	return
}
